/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel;

import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 负责接管http请求的WebWheel过滤器，通过在web.xml中设置此过滤器来使用WebWheel框架。<br>
 * <b>例：</b>
 * <pre>&lt;web-app ...>
   &lt;filter>
     &lt;filter-name>WebWheel&lt;/filter-name>
     &lt;filter-class>cn.webwheel.WebWheelFilter&lt;/filter-class>
     &lt;init-param>
       &lt;param-name>main&lt;/param-name>
       &lt;param-value>com.mysrc.WebMain&lt;/param-value>
     &lt;/init-param>
   &lt;/filter>
   &lt;filter-mapping>
     &lt;filter-name>WebWheel&lt;/filter-name>
     &lt;url-pattern>/*&lt;/url-pattern>
   &lt;/filter-mapping>
&lt;/web-app></pre>
 * 上面的com.mysrc.WebMain为用户写的类，作为应用程序的入口，必须以main参数的形式指定，并且此类必须继承自{@link cn.webwheel.Main}抽象类。<br>
 */
final public class WebWheelFilter implements javax.servlet.Filter {

    private Main main;

    /**
     * 生成并初始化main类
     */
    @SuppressWarnings("unchecked")
    public void init(FilterConfig filterConfig) throws ServletException {
        String s = filterConfig.getInitParameter("main");
        if (s == null) {
            throw new ServletException("parameter \"main\" must be set with WebWheelFilter in web.xml");
        }
        Class<? extends Main> cls;
        try {
            cls = (Class<? extends Main>) Class.forName(s);
        } catch (ClassNotFoundException e) {
            throw new ServletException("can not find class: " + s, e);
        }
        if (!Main.class.isAssignableFrom(cls)) {
            throw new ServletException("main class \"" + s + "\" must inherit class cn.webwheel.Main");
        }
        try {
            main = cls.newInstance();
        } catch (Exception e) {
            throw new ServletException("can not create instance of " + cls, e);
        }
        try {
            main.init0(filterConfig.getServletContext());
        } catch (RuntimeException e) {
            throw e;
        } catch (ServletException e) {
            throw e;
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /**
     * 根据动作映射配置情况处理http请求。<br>
     * 动作映射由{@link cn.webwheel.FilterGroup#bindAction(String, Class)}方法完成。
     * @see Main#root
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws IOException, ServletException {
        boolean solved;
        try {
            solved = main.process((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
        } catch (IOException e) {
            throw e;
        } catch (ServletException e) {
            throw e;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServletException(e);
        }
        if (!solved) {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    /**
     * 销毁main类
     */
    public void destroy() {
        main.destroy0();
        main = null;
    }
}
